<template>
  <el-form ref="element" :rules="rules" :model="model" :labelPosition="labelPosition" :require-asterisk-position="'right'" :disabled="disabled" class="a-form">
    <template v-for="(item, index) in list" :key="index">
      <el-form-item v-if="item.show" :prop="item.prop" :label="item['aria-label']" v-bind="{ ...formItemProps, ...item.formItemProps }">
        <template v-if="$slots[item.prop]">
          <slot :name="item.prop" :props="item"></slot>
        </template>
        <template v-else>
          <template v-if="item.type === 'input'">
            <el-input v-model="model[item.prop]" v-bind="item" />
          </template>
          <template v-if="item.type === 'textarea'">
            <el-input v-model="model[item.prop]" v-bind="item" type="textarea" />
          </template>
          <template v-if="item.type === 'select'">
            <el-select v-model="model[item.prop]" v-bind="item">
              <el-option v-for="(subItem, subIndex) in item.data || []" :key="subIndex" :label="subItem.label" :value="subItem.value" />
            </el-select>
          </template>
          <template v-if="item.type === 'daterange'">
            <el-date-picker v-model="model[item.prop]" v-bind="item" type="daterange" />
          </template>
          <template v-if="item.type === 'date'">
            <el-date-picker v-model="model[item.prop]" v-bind="item" type="date" />
          </template>
          <template v-if="item.type === 'month'">
            <el-date-picker v-model="model[item.prop]" v-bind="item" type="month" />
          </template>
          <template v-if="item.type === 'deptTree'">
            <a-dept v-model="model[item.prop]" v-bind="item" />
          </template>
          <template v-if="item.type === 'deptTree2'">
            <a-dept2 v-model="model[item.prop]" v-bind="item" />
          </template>
          <template v-if="item.type === 'upload'">
            <a-upload v-model="model[item.prop]" v-bind="item"></a-upload>
          </template>
        </template>
      </el-form-item>
    </template>
  </el-form>
</template>

<script setup lang="ts" generic="T extends FormItem,U extends FormModel">
import { reactive, ref } from 'vue'

defineOptions({
  name: 'a-form'
})

interface Props {
  list: T[]
  formProps?: Record<string, unknown>
  formItemProps?: Record<string, unknown>
  labelPosition?: 'top' | 'left'
  requireAsteriskPosition?: 'left' | 'right'
  disabled?: boolean
}

const model = defineModel<U>({ required: true })

const props = withDefaults(defineProps<Props>(), {
  disabled: false,
  labelPosition: 'top',
  requireAsteriskPosition: 'right'
})

const element = ref<FormInstance>()

const rules = reactive<FormRules>({})

props.list.forEach((item: FormItem) => {
  rules[item.prop] = item.rules

  if (item.show === undefined) item.show = true
  if (!item.placeholder) {
    if (item.type === 'input' || item.type === 'textarea') {
      item.placeholder = `请输入${item['aria-label']}`
    } else {
      item.placeholder = `请选择${item['aria-label']}`
    }
  }

  if (props.disabled || item.disabled) item.placeholder = ''

  if (item.clearable === undefined) item.clearable = true

  if (item.type === 'date' || item.type === 'daterange') {
    if (!item['value-format']) item['value-format'] = 'YYYY-MM-DD'
  }

  if (item.type === 'textarea') {
    if (!item.formItemProps || item.formItemProps.style === undefined) {
      item.formItemProps = {
        style: { width: '100%' }
      }
    }

    if (!item.rows) item.rows = 5
  }
})

defineExpose({
  element
})
</script>
